import os
import win32net
import win32security
import win32netcon
import ntsecuritycon
import win32api
import win32con
import socket


import config



def delete_shared_folder(share_name):
    try:
        win32net.NetShareDel(None, share_name, 0)
        return True
    except Exception as e:
        config.err_log(e)
        return False


def get_shared_folder():
    try:
        info = win32net.NetShareEnum(None, 2)
        return info[0]
    except Exception as e:
        config.err_log(e)
        return []


# 获取文件夹guest用户权限
def getauto_shared_folder(path):
    try:
        sd = win32security.GetFileSecurity(os.path.abspath(path), win32security.DACL_SECURITY_INFORMATION)
        dacl = sd.GetSecurityDescriptorDacl()
        sid, _, _ = win32security.LookupAccountName("", "Guest")
        auto = {"read":False, "write":False, "execute":False, "all":False}
        for i in range(dacl.GetAceCount()):
            ace = dacl.GetAce(i)
            if ace[2] == sid:
                access_mask = ace[1]
                if access_mask & 0x00000001:  # 读取权限
                    auto["read"] = True
                if access_mask & 0x00000002:  # 写入权限
                    auto["write"] = True
                if access_mask & 0x00000020:  # 执行权限
                    auto["execute"] = True
                if access_mask & 0x000F01FF == 0x000F01FF:  # 完全控制权限
                    auto["all"] = True
                return auto
        return auto
    except Exception as e:
        config.err_log(e)
        return False


# 修改文件夹guest用户权限 
def setauto_shared_folder(abs_path, permissions):
    try:
        sid = win32security.LookupAccountName("", "Guest")[0]
        sd = win32security.GetFileSecurity(abs_path, win32security.DACL_SECURITY_INFORMATION) 
        dacl = sd.GetSecurityDescriptorDacl()
        
        #删除原有权限
        for i in range(dacl.GetAceCount() - 1, -1, -1):
            ace = dacl.GetAce(i)
            if ace[2] == sid:
                dacl.DeleteAce(i)

        # 设置新权限
        access_mask = 0
        for permission in permissions:
            access_mask |= getattr(ntsecuritycon, permission) 
        ace_flags = win32security.OBJECT_INHERIT_ACE | win32security.CONTAINER_INHERIT_ACE
        dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, ace_flags, access_mask, sid)
        sd.SetSecurityDescriptorDacl(1, dacl, 0)
        win32security.SetFileSecurity(abs_path, win32security.DACL_SECURITY_INFORMATION, sd)
        return True
    except Exception as e:
        config.err_log(e)
        return False



def create_shared_folder(path, share_name, description, passwd=""):
    try:
        # 创建文件夹
        folder_path = os.path.join(config.CONFIG.CFG["folder_path"], path)
        try:
            os.remove(folder_path)
        except:
            pass
        os.makedirs(folder_path, exist_ok=True)
        # 权限设置
        setauto_shared_folder(folder_path, ["FILE_GENERIC_READ", "FILE_GENERIC_WRITE", "FILE_GENERIC_EXECUTE", "FILE_ALL_ACCESS"])
        # 获取本地计算机的信息
        server_info = win32net.NetServerGetInfo(None, 101)  # 2表示获取计算机信息

        # 设置共享信息
        share_info = {
            'netname': share_name,
            'type': win32netcon.STYPE_DISKTREE,
            'remark': description,
            'permissions': win32netcon.ACCESS_ALL,
            'max_uses': -1,
            'current_uses': 0,
            'path': folder_path,
            'passwd': passwd,  # 可以设置密码保护共享
            'security_descriptor': None  # 在这里稍后设置安全描述符
        }

        # 创建共享
        win32net.NetShareAdd(server_info['name'], 2, share_info)
        
        dacl = win32security.ACL()
        for val in ["Guest", "Administrator", "Everyone"]:
            sid = win32security.LookupAccountName(None, val)[0]
            dacl.AddAccessAllowedAce(win32security.ACL_REVISION, ntsecuritycon.FILE_ALL_ACCESS, sid) # 设置用户权限
        security_descriptor = win32security.SECURITY_DESCRIPTOR()
        security_descriptor.SetSecurityDescriptorDacl(1, dacl, 0)
        win32net.NetShareSetInfo(server_info['name'], share_name, 502, {'security_descriptor': security_descriptor, 'remark': description})
        return folder_path
    except Exception as e:
        config.err_log(e)
        return False




def setEnableLUA(value):
    # 打开注册表键
    key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System', 0, win32con.KEY_ALL_ACCESS)
    # 修改键值
    win32api.RegSetValueEx(key, 'EnableLUA', 0, win32con.REG_DWORD, value)
    # 再次读取键值以确认更改
    value, type_id = win32api.RegQueryValueEx(key, 'EnableLUA')
    print(f'Updated Value: {value}')
    # 关闭注册表键
    win32api.RegCloseKey(key)



# 修改本地策略 网络访问 本地账户的共享和安全模型 【1 仅来宾】 【0 经典】
def setforceguest(value):
    try:
        key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SYSTEM\\CurrentControlSet\\Control\\Lsa', 0, win32con.KEY_ALL_ACCESS)
        win32api.RegSetValueEx(key, 'forceguest', 0, win32con.REG_DWORD, value)
        win32api.RegCloseKey(key)
        return True
    except Exception as e:
        config.err_log(e)
        return False



# 修改本地策略 账户 使用空密码的本地账号进行登录控制  【1 启用】 【0 禁用】
def setLimitBlankPasswordUse(value):
    try:
        key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SYSTEM\\CurrentControlSet\\Control\\Lsa', 0, win32con.KEY_ALL_ACCESS)
        win32api.RegSetValueEx(key, 'LimitBlankPasswordUse', 0, win32con.REG_DWORD, value)
        win32api.RegCloseKey(key)
        return True
    except Exception as e:
        config.err_log(e)
        return False



# 修改本地策略 来宾账户状态 【0】 【1】
def setuserflags(disable):
    try:
        user_info = win32net.NetUserGetInfo(None, "Guest", 1)
        if disable:
            user_info["flags"] &= ~win32netcon.UF_ACCOUNTDISABLE
        else:
            user_info["flags"] |= win32netcon.UF_ACCOUNTDISABLE
        win32net.NetUserSetInfo(None, "Guest", 1, user_info)
        return True
    except Exception as e:
        config.err_log(e)
        return False


# 修改共享中心密码保护共享 【0】 【1】
def setActSysAc(disable):
    try:
        if disable:
            value = b'A\x00\x00\x00'
        else:
            value = b'\xc1\x00\x00\x00'
        key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SECURITY\\Policy\\Accounts\\{}\\ActSysAc'.format(win32security.ConvertSidToStringSid(win32security.LookupAccountName(None, "Guest")[0])) , 0, win32con.KEY_ALL_ACCESS)
        win32api.RegSetValueEx(key, '', 0, win32con.REG_NONE, value)
        win32api.RegCloseKey(key)
        return True
    except Exception as e:
        config.err_log(e)
        return False



# 清除本地共享链接缓存用户
def clear_ClentUser():
    #level = 1
    #resume_handle = 0
    sessions = win32net.NetSessionEnum(10, socket.gethostname())
    [win32net.NetSessionDel(None, session['client_name'], session['user_name']) for session in sessions]
    return True



def getallregkey():
    try:
        key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SYSTEM\\CurrentControlSet\\Control\\Lsa', 0, win32con.KEY_ALL_ACCESS)
        regkeys = []
        regkeys.append(win32api.RegQueryValueEx(key, 'forceguest')[0]) # 获取 本地账户的共享和安全模型
        regkeys.append(win32api.RegQueryValueEx(key, 'LimitBlankPasswordUse')[0]) # 使用空密码的本地账号进行登录控制
        win32api.RegCloseKey(key)
        user_info = win32net.NetUserGetInfo(None, "Guest", 1)
        # 获取 来宾账号状态
        if user_info["flags"] == 66145:
            regkeys.append(1)
        else:
            regkeys.append(0)
        key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SECURITY\\Policy\\Accounts\\{}\\ActSysAc'.format(win32security.ConvertSidToStringSid(win32security.LookupAccountName(None, "Guest")[0])) , 0, win32con.KEY_ALL_ACCESS)
        # 获取 共享密码保护
        if win32api.RegQueryValueEx(key, '')[0] == b'A\x00\x00\x00':
            regkeys.append(1)
        else:
            regkeys.append(0)
        win32api.RegCloseKey(key)
        return regkeys
    except Exception as e:
        config.err_log(e)
        return None